﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using RoofRunner.GameComponents.Rendering;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace RoofRunner.Actors.ActorComponents
{
    public class Skull : Actor
    {
        #region Constructors
        public Skull(Vector3 position)
            : base(position)
        {
            this.AddComponent(new SkullMovement(position, position + new Vector3(0, 0, -40), 5.0f));
            this.AddComponent(new SkullComponent());
        }
        #endregion // Constuctors

        private class SkullMovement : ActorComponent
        {
            #region Properties
            public Vector3 StartPoint { get; set; }
            public Vector3 EndPoint { get; set; }
            private float Duration { get; set; }
            private bool MoveToEnd { get; set; }

            private Vector3 Step { get; set; }
            private float Elapsed { get; set; }
            #endregion // Properties


            #region Constructors
            public SkullMovement(Vector3 startPoint, Vector3 endPoint, float duration)
                : base()
            {
                this.StartPoint = startPoint;
                this.EndPoint = endPoint;
                this.Duration = duration;

                this.Step = (this.EndPoint - this.StartPoint) / this.Duration;
                this.MoveToEnd = true;
                this.Elapsed = 0.0f;
            }
            #endregion // Constructors


            #region Methods
            public override void Update(GameTime gameTime)
            {
                Elapsed += (float)gameTime.ElapsedGameTime.TotalSeconds;
                if (Elapsed >= this.Duration)
                {
                    this.MoveToEnd = !this.MoveToEnd;
                    this.Elapsed -= this.Duration;
                }

                var factor = this.Step * this.Elapsed * (this.MoveToEnd ? 1 : -1);
                Vector3 tmpStep = (MoveToEnd ? this.StartPoint : this.EndPoint) + factor;
                this.Parent.Position = tmpStep;



                base.Update(gameTime);
            }
            #endregion // Methods
        }



        private class SkullComponent : ActorComponent
        {
            #region Properties
            private Model Skull { get; set; }
            private TextureCube EnvironmentMapTexture { get; set; }
            #endregion // Properties


            public override void LoadContent(ContentManager content)
            {
                this.Skull = content.Load<Model>("Skull\\skullocc");
                this.EnvironmentMapTexture = content.Load<TextureCube>("Sky\\SkyBoxTex");

                foreach (ModelMesh mesh in this.Skull.Meshes)
                {
                    foreach (Effect eff in mesh.Effects)
                    {
                        eff.Parameters["tex"].SetValue(this.EnvironmentMapTexture);
                    }
                }
                base.LoadContent(content);
            }


            public override void Render(GameTime gameTime, RenderWorld renderWorld)
            {
                Matrix w = Matrix.CreateWorld(this.Parent.Position, this.Parent.Forward, this.Parent.Up);
                Matrix wvp = w * renderWorld.Camera.View * renderWorld.Camera.Projection;
                foreach (ModelMesh mesh in Skull.Meshes)
                {
                    foreach (Effect eff in mesh.Effects)
                    {
                        eff.Parameters["WVP"].SetValue(wvp);
                        eff.Parameters["World"].SetValue(w);
                        eff.Parameters["eyePosition"].SetValue(renderWorld.Camera.Position);
                        eff.CurrentTechnique.Passes[0].Apply();
                        mesh.Draw();
                    }
                }

                base.Render(gameTime, renderWorld);
            }
        }
    }
}
